package com.gadarts.parashoot.enemies;

import java.util.ArrayList;
import java.util.List;

import android.graphics.Bitmap;
import android.graphics.Rect;

import com.gadarts.parashoot.GameModel;
import com.gadarts.parashoot.GameView;
import com.gadarts.parashoot.Sprite;
import com.gadarts.parashoot.player.Bunker;
import com.gadarts.parashoot.utils.C;
import com.gadarts.parashoot.utils.Utils;
import com.gadarts.parashoot.utils.ViewUtils;
import com.gadarts.parashoot.weapons.Bullet;

public abstract class SoldierEnemy extends Enemy {

	protected Rect parachuteMask, bodyMask;// The X and Y ranges for the parts.
	private boolean landed;
	private String reloadTimer;// The timer name of the gun reload.

	public SoldierEnemy(GameModel model, GameView view,
			ArrayList<Sprite> sprites, int x, int y, int speed, int direction,
			int depth, int health, boolean fitFrameToDirection, Bitmap bodyPart) {
		super(model, view, sprites, x, y, speed, direction, depth, health,
				fitFrameToDirection, bodyPart);
	}

	@Override
	public void update() {
		super.update();
		if (!dead) {
			checkHealth();
			checkCollisions();
			shoot();
		} else if (deadTimer != null) {
			if (Utils.checkTiming(model, deadTimer,
					C.Enemies.Paratroopers.Infantry.DEAD_TIME))
				model.destroyObject(this, SoldierEnemy.class);
		}
	}

	private void shoot() {
		if (landed)
			if (Utils.checkTiming(model, reloadTimer,
					C.Enemies.Paratroopers.Infantry.RELOAD_TIME))
				resetAnimation(C.Enemies.Paratroopers.Infantry.ANIMATION_SPEED);
	}

	// Checks collisions between objects.
	protected void checkCollisions() {

		updateRects();

		List<Bullet> bulletsList = model.getBulletsList();
		// Check collisions between with bullets.
		for (int j = 0; j < bulletsList.size(); j++) {

			Bullet currentBullet = bulletsList.get(j);
			if (ViewUtils.checkCollisionPartial(bodyMask,
					currentBullet.getCenterX(), currentBullet.getCenterY())) {
				setHealth(health - C.Weapons.CannonBall.DAMAGE);
				model.createExplosion(currentBullet.getX(),
						currentBullet.getY(), 0);
				model.createSmoke(currentBullet.getX(), currentBullet.getY(), 1);

				if (health <= 0) {
					createRandomFlyingParts(4, false);
					model.destroyObject(this, SoldierEnemy.class);
				}

				model.destroyObject(currentBullet, Bullet.class);
				return;
			} else if (ViewUtils.checkCollisionPartial(parachuteMask,
					currentBullet.getCenterX(), currentBullet.getCenterY())) {
				if (!gravityStatus) {
					model.createExplosion(currentBullet.getX(),
							currentBullet.getY(), 0);
					model.createSmoke(currentBullet.getX(),
							currentBullet.getY(), 1);

					destroyParachute();

					model.destroyObject(currentBullet, Bullet.class);
					break;
				}
			}
		}

		List<AirCraftEnemy> crashingCraftsList = model.getAirCraftsList();
		// Check collisions with falling air-crafts.
		for (int j = 0; j < crashingCraftsList.size(); j++) {
			AirCraftEnemy currentCraft = crashingCraftsList.get(j);
			if (ViewUtils.checkCollisionPartial(bodyMask,
					currentCraft.getCenterX(), currentCraft.getCenterY())) {
				createRandomFlyingParts(4, false);
				model.destroyObject(this, SoldierEnemy.class);
				return;
			} else if (ViewUtils.checkCollisionPartial(parachuteMask,
					currentCraft.getCenterX(), currentCraft.getCenterY())) {
				if (!gravityStatus && !landed) {
					destroyParachute();
					break;
				}
			}
		}

		if (!landed)
			if (isTouchingGround()) {
				if (gravityStatus)
					model.destroyObject(this, SoldierEnemy.class);
				else
					land();
			}

	}

	// Change to standing soldier once landing with parachute.
	protected void land() {
		Bunker player = model.getBunker();
		if (x < player.getCenterX()) {
			direction = C.InGame.DIRECTION_RIGHT;
		} else {
			direction = C.InGame.DIRECTION_LEFT;
		}

		reloadTimer = Utils.setTimer(model,
				C.Enemies.Paratroopers.Infantry.RELOAD_TIMER_NAME);
		landed = true;
		speed = 0;
	}

	// Changes the soldier to falling man.
	private void destroyParachute() {
		setSprite(view
				.getSprite(C.Enemies.Paratroopers.Infantry.FALLING_IMAGE_NAME));
		loop = true;
		gravityStatus = true;
	}

	// Updates the ranges for the parts.
	private void updateRects() {
		int parachuteBottom = C.Enemies.Paratroopers.Infantry.PARACHUTE_BOTTOM;
		int width = getImage().getWidth();
		parachuteMask.left = x;
		parachuteMask.right = x + width;
		parachuteMask.top = y;
		parachuteMask.bottom = y + parachuteBottom;
		bodyMask.left = x + width / 4;
		bodyMask.right = x + width * 3 / 4;
		bodyMask.top = y + parachuteBottom;
		bodyMask.bottom = y + getImage().getHeight();
	}

	public boolean isOnGround() {
		return landed;
	}

	public boolean isDead() {
		return dead;
	}

}
